package com.rin.service;

import com.rin.constant.FileConstant;
import com.rin.constant.OperationEnum;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;

/**
 * @author RinMi
 * @since 2023/6/13
 */

@Service
public class BaseService {

    @Resource
    private FileSystem fileSystem;

    public void upload(ByteArrayInputStream inputStream, String destination) {
        try {
            OutputStream out = fileSystem.create(new Path(destination));
            // 使用Hadoop提供的IOUtils，将in的内容copy到out，设置buffSize大小，是否关闭流设置true
            IOUtils.copyBytes(inputStream, out, 4096, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public InputStream download(String destination) {
        try {
            // 调用open方法进行下载，参数HDFS路径
            return fileSystem.open(new Path(destination));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void delete(String destination) {
        try {
            // 调用delete方法，删除指定的文件。参数:false:表示是否递归删除
            fileSystem.delete(new Path(destination), false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean mkdir(String directory) {
        boolean flag;
        try {
            // 调用mkdirs方法，在HDFS文件服务器上创建文件夹。
            flag = fileSystem.mkdirs(new Path(directory));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return flag;
    }

    public String createDestination(Class<?> clazz, String entityId) {
        return "/" + clazz.getSimpleName() + "/" + entityId + ".txt";
    }

    /**
     * 获取id列表
     *
     * @param entity 实体
     * @return id列表
     */
    public List<String> selectIdList(Object entity) {
        //id列表
        List<String> idList = new LinkedList<>();
        //目标地址
        String destination = createDestination(entity.getClass(), FileConstant.ID);
        //字节流
        InputStream inputStream = download(destination);
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String line;
        try {
            while ((line = bufferedReader.readLine()) != null) {
                idList.add(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                inputStreamReader.close();
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return idList;
    }

    public int checkId(Object entity, String entityId) {
        List<String> idList = selectIdList(entity);
        return idList.stream().anyMatch(entityId::equals) ? 1 : 0;
    }

    public void insertIdList(Object entity, List<String> idList) {
        String destination = createDestination(entity.getClass(), FileConstant.ID);
        delete(destination);
        String separator = System.getProperty("line.separator");
        StringBuilder stringBuilder = new StringBuilder();
        idList.forEach(id -> stringBuilder.append(id).append(separator));
        //将字符串转化为字节流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
        //上传
        upload(byteArrayInputStream, destination);
    }

    public void updateIdList(Object entity, String id, int operation) {
        List<String> idList = selectIdList(entity);
        if (operation == OperationEnum.INSERT.ordinal()) {
            idList.add(id);
        } else {
            idList.remove(id);
        }
        String destination = createDestination(entity.getClass(), FileConstant.ID);
        delete(destination);
        insertIdList(entity, idList);
    }

    public void updateIdList(Object entity, List<String> idList, int operation) {
        List<String> curIdList = selectIdList(entity);
        if (operation == OperationEnum.INSERT.ordinal()) {
            curIdList.addAll(idList);
        } else {
            curIdList.removeAll(idList);
        }
        String destination = createDestination(entity.getClass(), FileConstant.ID);
        delete(destination);
        insertIdList(entity, curIdList);
    }

    public String getLastId(Object entity) {
        List<String> idList = selectIdList(entity);
        if (idList.isEmpty()){
            return null;
        }else{
            return idList.get(idList.size() - 1);
        }
    }

    public void initRepository(Object entity) throws IOException {
        String destination = createDestination(entity.getClass(), FileConstant.ID);
        Path path = new Path(destination);
        if (fileSystem.exists(path)){
            return;
        }
        fileSystem.createNewFile(path);
    }
}
